#ifndef DATAOBJECT_H
#define DATAOBJECT_H

#include <windows.h>
#include <shldisp.h>
#include <fstream>
#include <functional>

class DataObject : public IDataObject, public IDataObjectAsyncCapability {
public:
    DataObject(IDataObject* core, std::function<void(const char*, DWORD)> comp, LPCSTR share);
    ~DataObject();

    // IUnknown members
    HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObject);
    ULONG __stdcall AddRef(void);
    ULONG __stdcall Release(void);

    // IDataObject members
    HRESULT __stdcall GetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium);
    HRESULT __stdcall GetDataHere(FORMATETC* pFormatEtc, STGMEDIUM* pMedium);
    HRESULT __stdcall QueryGetData(FORMATETC* pFormatEtc);
    HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC* pFormatEct,
                                            FORMATETC* pFormatEtcOut);
    HRESULT __stdcall SetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium,
                              BOOL fRelease);
    HRESULT __stdcall EnumFormatEtc(DWORD dwDirection,
                                    IEnumFORMATETC** ppEnumFormatEtc);
    HRESULT __stdcall DAdvise(FORMATETC* pFormatEtc, DWORD advf,
                              IAdviseSink* pAdvSink, DWORD* pdwConnection);
    HRESULT __stdcall DUnadvise(DWORD dwConnection);
    HRESULT __stdcall EnumDAdvise(IEnumSTATDATA** ppEnumAdvise);

    //IDataObjectAsyncCapability members
    HRESULT __stdcall StartOperation(IBindCtx* pbcReserved);
    HRESULT __stdcall InOperation(BOOL* pfInAsyncOp);
    HRESULT __stdcall EndOperation(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
    HRESULT __stdcall GetAsyncMode(BOOL* pfIsOpAsync);
    HRESULT __stdcall SetAsyncMode(BOOL fDoOpAsync);

private:
    IDataObject* m_core;
    LONG m_lRefCount;
    BOOL m_inOp;
    BOOL m_supportAsync;
    std::string m_share;
    std::function<void(const char*, DWORD)> m_sendCompletion;
};

#endif // DATAOBJECT_H
